<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import { fabric } from "fabric";
import {
  actionHandler,
  anchorWrapper,
  polygonPositionHandler,
} from "./FabricUtil";
import * as GRAPHY from "./graphy";
import points from "./polyline1";
import { Vector2 } from "three";

const canvas = ref(null);

const geometryInfo = reactive({
  scaleX: 0,
  angle: 0,
  left: 0,
  top: 0,
  skewX: 0,
  skewY: 0,
});

onMounted(() => {
  var canvas = new fabric.Canvas("canvasfabric", { selection: false });

  //所有图形的绘制起点都是中间点,开启后，每个图形变化时，坐标原点会随着变动而变动；
  // fabric.Object.prototype.originX = fabric.Object.prototype.originY = "center";

  const initEvent = () => {
    //   监听鼠标点击事件
    canvas.on("mouse:down", (options) => {
      // console.log(
      //   `x轴坐标: ${options.e.clientX};    y轴坐标: ${options.e.clientY}`
      // );
    });

    //画布支持缩放
    canvas.on("mouse:wheel", (opt) => {
      let delta = opt.e.deltaY; // 滚轮向上滚一下是 -100，向下滚一下是 100
      let zoom = canvas.getZoom(); // 获取画布当前缩放值
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      canvas.setZoom(zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
    });
  };
  
  const createPolyline = (coords: object[], options = {}) => {
    let strokeWidth = 1;
    var geometry = new fabric.Polyline(coords, {
      // name: "myPolyline",
      fill: "",
      stroke: "#0000ff",
      strokeWidth: strokeWidth,
      objectCaching: false,
      transparentCorners: false,
      cornerColor: "red",
      hasBorders: false,
      hasControls: true,
      //   lockMovementX:true,//禁止水平方向移动
      //   lockMovementY:true,//禁止垂直方向移动
      //   angle: 30, //旋转角度
      //   backgroundColor: "#ccc", //背景色
      //   borderDashArray: [1, 3],  //指定对象边框的破折号图案的数组（hasBorder 必须为真）,设置为虚线
      borderOpacityWhenMoving: 0.1, //拖拽移动时边框线的透明度
      borderScaleFactor: 3, //边框线条的粗细
      corner: 1,
      ...options,
    });

    geometry?.on("selected", function (options: any) {
      // console.log("selected", options);
    });

    geometry?.on("mousedblclick", function (options: any) {
      console.log("mousedblclick", options);

      options.target.set("stroke", "grey");
      let x = options.absolutePointer.x,
        y = options.absolutePointer.y,
        left = options.target.left,
        top = options.target.top;

      let points = options.target.points.map((point) => [point.x, point.y]);

      let minCoords = getStartCoords(points);

      let translationLeft = left - minCoords.left;
      let translationTop = top - minCoords.top;

      console.log("x", x, "y", y);
      console.log("points1", points);
      points = points.map((point) => {
        return [point[0] + translationLeft, point[1] + translationTop];
      });
      console.log("points2", points);

      let minPoint = {
        dist: Infinity, //距离
        point: [], //垂足坐标
        index: 0, //第几条线段上，从1开始
      };
      points.reduce((pre, next, index) => {
        let r = GRAPHY.pointToSegmentDist([x, y], pre, next);
        if (r.type == 0 && minPoint.dist > r.dist) {
          minPoint["index"] = index;
          minPoint["dist"] = r.dist;
          minPoint["point"] = r.point;
        }
        return next;
      });
      if (minPoint.index === -1) {
        console.log("不存在分割点");
        return;
      }
      // 拆分坐标点
      let polylineCoords1 = points;
      let polylineCoords2 = polylineCoords1.splice(minPoint.index);
      let splitPoint = [minPoint["point"][0], minPoint["point"][1]];

      var c = new fabric.Circle({
        name: "circle100",
        left: splitPoint[0] - 6,
        top: splitPoint[1] - 6,
        strokeWidth: 1,
        radius: 6,
        fill: "#ff0",
        stroke: "#000",
      });

      canvas.add(c);

      polylineCoords1.push(splitPoint);
      polylineCoords2.unshift(splitPoint);

      createPolyline(transformCoords(polylineCoords1));
      const polyline = createPolyline(transformCoords(polylineCoords2));
      setTimeout(() => {
        canvas.remove(options.target);
      }, 100);

      canvas.setActiveObject(polyline);
      canvas.requestRenderAll();

      function getStartCoords(points) {
        let left = Math.min(...points.map((point) => point[0]));
        let top = Math.min(...points.map((point) => point[1]));
        return {
          left,
          top,
        };
      }
      function transformCoords(points) {
        return points.map((point) => {
          return {
            x: point[0],
            y: point[1],
          };
        });
      }
    });

    //修改控制框样式和交互方式
    const lastControl = (geometry as any).points.length - 1;
    geometry.cornerStyle = "circle";
    geometry.cornerColor = "rgba(255,0,0,1)";
    (geometry as any).controls = (geometry as any).points.reduce(
      (acc, point, index) => {
        acc["p" + index] = new fabric.Control({
          positionHandler: polygonPositionHandler,
          actionHandler: anchorWrapper(
            index > 0 ? index - 1 : lastControl,
            actionHandler
          ),
          actionName: "modify",
          pointIndex: index,
        } as Partial<Control>);
        return acc;
      },
      {}
    );

    canvas.add(geometry);
    return geometry;
  };

  initEvent();
  const polyline = createPolyline([
    { x: 100, y: 50 },
    { x: 150, y: 100 },
    { x: 100, y: 150 },
    { x: 200, y: 200 },
  ]);
  // const polyline = createPolyline(
  //   points.map((point) => {
  //     return new Vector2(point[0], point[1]).divideScalar(5);
  //   })
  // );

  canvas.setActiveObject(polyline); //默认激活

  canvas.on("object:modified", function (e) {
    console.log(`修改了:${e.target.name}`, e);
  });

  function updateControls() {
    geometryInfo.scaleX = polyline.scaleX;
    geometryInfo.angle = polyline.angle;
    geometryInfo.left = polyline.left;
    geometryInfo.top = polyline.top;
    geometryInfo.skewX = polyline.skewX;
    geometryInfo.skewY = polyline.skewY;
  }
  updateControls();

  canvas.on({
    "object:moving": updateControls,
    "object:scaling": updateControls,
    "object:resizing": updateControls,
    "object:rotating": updateControls,
    "object:skewing": updateControls,
    "object:modified": updateControls,
  });
});
</script>

<template>
  <p>使用fabric.polyline实现,双击切割</p>
  <div>
    <span v-for="(val, key) in geometryInfo" :key="key">
      {{ key }}:{{ val }} &nbsp;
    </span>
  </div>

  <canvas id="canvasfabric" width="400" height="400" ref="canvas"></canvas>
</template>

<style lang="scss">
#canvasfabric {
  background-color: #eee;
}
</style>
